<script>
  // instanceof 原理：用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性
  function Person() {
  }
  function Foo() {
  }

  // //显示改变Foo.prototype指向Person的实例对象（原型继承）
  // Foo.prototype = new Person()
  // Foo.prototype = {}
  let a = new Foo()

  console.log(a.__proto__ === Foo.prototype); //true

  console.log(a instanceof Foo);//true

  console.log(Foo.prototype.__proto__ === Person.prototype);//true

  console.log(a instanceof Person);//true

  console.log(a instanceof Object);//true

  // 这个时候改变Foo.prototype的指向

  // Foo.prototype = {}
  // a = new Foo()

  // Foo.prototype已经不在a的原型链上面了

  console.log(a.__proto__ === Foo.prototype);//false

  console.log(a instanceof Foo);//false

  //Person.prototype依然在a的原型链上面

  console.log(a instanceof Person);//true
</script>

<script>
  // 对象|函数|构造函数（constructor）|原型||new|__proto__|prototype|instanceof|继承|模拟类 的理解

  // 对象 __proto__ constructor 属性的理解

  // 函数 既是函数也是对象，特有属性是 prototype 实现[[call]] 的对象

  // 构造函数（constructor），不能是箭头函数， 实现 [[construct]] 的对象 new 的原理其实就是 [[construct]] 私有方法的实现

  // 原型 查找原型链用 __proto__, function.prototype 指向一个原型对象

  // new原理： 生成一个 obj, obj.__proto__ = 构造函数.prototype，等价于 let obj = Object.create(构造函数.prototype)
  // 执行构造函数，假设构造函数有返回对象或者函数，那就返回，否则返回本次创建的对象

  // __proto__ 函数和对象都有的属性，浏览器实现方法，查找原型链的方式，用于查找 原型对象

  // prototype 函数特有属性，指向原型对象，为实例所共享

  // instanceof 原理是 实例.__proto__ === 构造函数.prototype

  // 继承 原型继承，构造继承，组合继承（原型+构造），拷贝继承，实例继承，寄生组合继承

  // 模拟类 语法糖 es6 class super constructor

  // 校验类型 typeof instanceof Object.prototype.toString.call()
  // typeof 有设计缺陷
  // 现在来说 instanceof 已经是安全的了，浏览器不允许 修改内置对象的 prototype 了
  // Array.isArray()
  // Array.of() Array.from()
  // Object.is() Object.assign() Object.create()
  // constructor


  // js 运行时的7种基本数据类型
  // Undefined Null Boolean Number String Symbol Object
  // 浏览器宿主对象(window, dom, web api 接口)
  // js内置对象(固有(%Array%)，原生(Array, Date, RegExp)，普通, 对象的特殊行为)
</script>
